#ifndef INDEX_MANAGER_H
#define INDEX_MANAGER_H

#include "../../include/gudb.h"
#include "../memory/memory_manager.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdatomic.h>

// Forward declarations
typedef struct index_manager index_manager_t;
typedef struct index_interface index_interface_t;
typedef struct index_instance index_instance_t;
typedef struct index_iterator index_iterator_t;

// Index types supported by the system
typedef enum {
    INDEX_TYPE_BW_TREE = 0,     // Bw-Tree (lock-free B+ tree)
    INDEX_TYPE_BTREE,           // Traditional B+ tree (lock-based)
    INDEX_TYPE_HASH,            // Hash index for equality lookups
    INDEX_TYPE_BITMAP,          // Bitmap index for low-cardinality data
    INDEX_TYPE_RTREE,           // R-tree for spatial data
    INDEX_TYPE_COUNT            // Number of index types
} index_type_t;

// Index operation result codes
typedef enum {
    INDEX_SUCCESS = 0,
    INDEX_ERROR_KEY_NOT_FOUND,
    INDEX_ERROR_KEY_EXISTS,
    INDEX_ERROR_INVALID_PARAM,
    INDEX_ERROR_OUT_OF_MEMORY,
    INDEX_ERROR_TYPE_MISMATCH,
    INDEX_ERROR_INDEX_FULL,
    INDEX_ERROR_CONCURRENT_UPDATE,
    INDEX_ERROR_DESTROYED
} index_result_t;

// Index search result
typedef struct index_search_result {
    bool found;                 // Whether key was found
    void* value;               // Found value (if any)
    size_t value_size;         // Size of found value
    uint64_t record_id;        // Record ID (for database integration)
} index_search_result_t;

// Index configuration parameters
typedef struct index_config {
    index_type_t type;         // Index type
    uint32_t initial_capacity; // Initial capacity hint
    uint32_t max_key_size;     // Maximum key size
    uint32_t max_value_size;   // Maximum value size
    double load_factor;        // Load factor (for hash indexes)
    uint32_t node_size;        // Node size (for tree indexes)
    uint32_t bucket_count;     // Bucket count (for hash indexes)
    bool allow_duplicates;     // Whether to allow duplicate keys
    bool is_unique;            // Whether index enforces uniqueness
    bool is_primary;           // Whether this is a primary key index
} index_config_t;

// Index statistics
typedef struct index_stats {
    uint64_t total_keys;       // Total number of keys
    uint64_t total_operations; // Total operations performed
    uint64_t searches;         // Number of search operations
    uint64_t inserts;          // Number of insert operations
    uint64_t deletes;          // Number of delete operations
    uint64_t updates;          // Number of update operations
    uint64_t range_scans;      // Number of range scan operations
    size_t memory_usage;       // Current memory usage in bytes
    double avg_chain_length;   // Average chain length (for hash)
    double avg_depth;          // Average tree depth (for trees)
    uint64_t collisions;       // Number of hash collisions
    uint64_t rehashes;         // Number of rehash operations
} index_stats_t;

// Generic index iterator
struct index_iterator {
    index_instance_t* index;   // Index instance
    void* internal_state;      // Iterator internal state
    bool is_valid;             // Whether iterator is valid
    bool forward;              // Scan direction
    void* current_key;         // Current key
    size_t current_key_size;   // Current key size
    void* current_value;       // Current value
    size_t current_value_size; // Current value size
};

// Index interface - virtual function table
struct index_interface {
    // Core operations
    index_result_t (*insert)(index_instance_t* index, const void* key, size_t key_size,
                             const void* value, size_t value_size);
    index_result_t (*delete)(index_instance_t* index, const void* key, size_t key_size);
    index_result_t (*update)(index_instance_t* index, const void* key, size_t key_size,
                             const void* value, size_t value_size);
    index_result_t (*search)(index_instance_t* index, const void* key, size_t key_size,
                             index_search_result_t* result);
    
    // Range operations (if supported)
    index_iterator_t* (*range_scan)(index_instance_t* index, 
                                   const void* start_key, size_t start_key_size,
                                   const void* end_key, size_t end_key_size,
                                   bool forward);
    
    // Iterator operations
    bool (*iterator_valid)(index_iterator_t* iter);
    index_result_t (*iterator_next)(index_iterator_t* iter);
    index_result_t (*iterator_current)(index_iterator_t* iter, 
                                      void** key, size_t* key_size,
                                      void** value, size_t* value_size);
    void (*iterator_destroy)(index_iterator_t* iter);
    
    // Bulk operations (optional)
    index_result_t (*bulk_insert)(index_instance_t* index, 
                                 const void** keys, size_t* key_sizes,
                                 const void** values, size_t* value_sizes,
                                 size_t count);
    size_t (*range_delete)(index_instance_t* index,
                          const void* start_key, size_t start_key_size,
                          const void* end_key, size_t end_key_size);
    
    // Management operations
    index_result_t (*clear)(index_instance_t* index);
    index_result_t (*rebuild)(index_instance_t* index);
    void (*destroy)(index_instance_t* index);
    
    // Statistics and monitoring
    void (*get_stats)(index_instance_t* index, index_stats_t* stats);
    bool (*validate)(index_instance_t* index);
    
    // Configuration
    index_result_t (*set_config)(index_instance_t* index, const index_config_t* config);
    void (*get_config)(index_instance_t* index, index_config_t* config);
};

// Index instance - contains actual index data and interface
struct index_instance {
    index_type_t type;         // Index type
    index_interface_t* interface; // Virtual function table
    void* index_data;          // Type-specific index data
    index_config_t config;     // Index configuration
    memory_manager_t* memory_mgr; // Memory manager
    pthread_rwlock_t rwlock;   // Reader-writer lock for thread safety
    atomic_bool is_destroyed;  // Destruction flag
    index_stats_t stats;       // Index statistics
    char name[256];            // Index name
};

// Index manager - manages multiple indexes
struct index_manager {
    index_instance_t** indexes; // Array of index instances
    uint32_t capacity;         // Index array capacity
    uint32_t count;            // Number of active indexes
    memory_manager_t* memory_mgr; // Memory manager
    pthread_rwlock_t rwlock;   // Reader-writer lock
    
    // Index type factories
    index_interface_t* type_interfaces[INDEX_TYPE_COUNT];
    
    // Statistics
    uint64_t total_indexes_created;
    uint64_t total_operations;
};

// Index Manager API

// Lifecycle management
index_manager_t* index_manager_create(memory_manager_t* memory_mgr);
void index_manager_destroy(index_manager_t* mgr);

// Index creation and management
index_instance_t* index_create(index_manager_t* mgr, const char* name, 
                              const index_config_t* config);
index_result_t index_drop(index_manager_t* mgr, const char* name);
index_instance_t* index_get(index_manager_t* mgr, const char* name);
index_result_t index_rebuild(index_manager_t* mgr, const char* name);

// Generic index operations (delegates to specific implementation)
index_result_t index_insert(index_instance_t* index, const void* key, size_t key_size,
                           const void* value, size_t value_size);
index_result_t index_delete(index_instance_t* index, const void* key, size_t key_size);
index_result_t index_update(index_instance_t* index, const void* key, size_t key_size,
                           const void* value, size_t value_size);
index_result_t index_search(index_instance_t* index, const void* key, size_t key_size,
                           index_search_result_t* result);

// Range operations
index_iterator_t* index_range_scan(index_instance_t* index,
                                  const void* start_key, size_t start_key_size,
                                  const void* end_key, size_t end_key_size,
                                  bool forward);
bool index_iterator_valid(index_iterator_t* iter);
index_result_t index_iterator_next(index_iterator_t* iter);
index_result_t index_iterator_current(index_iterator_t* iter,
                                     void** key, size_t* key_size,
                                     void** value, size_t* value_size);
void index_iterator_destroy(index_iterator_t* iter);

// Bulk operations
index_result_t index_bulk_insert(index_instance_t* index,
                                const void** keys, size_t* key_sizes,
                                const void** values, size_t* value_sizes,
                                size_t count);
size_t index_range_delete(index_instance_t* index,
                         const void* start_key, size_t start_key_size,
                         const void* end_key, size_t end_key_size);

// Configuration and management
index_result_t index_clear(index_instance_t* index);
void index_get_stats(index_instance_t* index, index_stats_t* stats);
bool index_validate(index_instance_t* index);
void index_print_stats(index_instance_t* index);

// Utility functions
const char* index_type_to_string(index_type_t type);
const char* index_result_to_string(index_result_t result);
index_config_t index_default_config(index_type_t type);

// Type-specific factory functions (implemented in separate files)
index_interface_t* bw_tree_interface_create(void);
index_interface_t* btree_interface_create(void);
index_interface_t* hash_index_interface_create(void);
index_interface_t* bitmap_index_interface_create(void);
index_interface_t* rtree_interface_create(void);

#endif // INDEX_MANAGER_H